import { app, shell, BrowserWindow, ipcMain, screen, dialog, Tray, Menu } from 'electron'
import fs from 'fs/promises'
import { join } from 'path'
import path from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/ball.png?asset'
import { readdir, readFile } from 'fs/promises'
import { initUpdater } from './update'
import { existsSync, mkdirSync } from 'fs'

let mainWindow: BrowserWindow | null = null;

function createWindow(): void {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    show: false,
    frame: false,
    resizable: false,
    transparent: true,
    autoHideMenuBar: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow?.show()
  })

  //窗口拖拽
  ipcMain.handle('custom-adsorption', (_, data) => {
    let x = data.appX;
    let y = data.appY;
    mainWindow?.setPosition(x, y);
  })

  //关闭窗口
  ipcMain.handle('close-window', () => {
    mainWindow?.close();
  })

  //隐藏窗口到托盘
  let tray: Tray | null = null;
  let isVisible = true;
  if (!tray) {
    tray = new Tray(icon)
    // 设置 titlle
    tray.setToolTip('iBear')
    tray.setTitle('iBear')
  }
  ipcMain.handle('hide-to-tray', () => {
    if (mainWindow?.isVisible()) {
      mainWindow.hide()
      isVisible = false;
    }
  })

  // 监听托盘右键事件
  tray.on('right-click', () => {
    // 右键菜单模板
    const contextMenu = Menu.buildFromTemplate([
      {
        label: '退出应用       ',
        type: 'normal',
        click: app.quit,
      },
    ])
    if (tray) tray.setContextMenu(contextMenu)
  })

  //监听点击托盘的事件
  tray.on('click', () => {
    // 这里来控制窗口的显示和隐藏
    if (isVisible) {
      mainWindow?.hide()
      isVisible = false;
    } else {
      mainWindow?.show()
      isVisible = true;
    }
  })

  //最小化窗口
  ipcMain.handle('minimize-window', () => {
    mainWindow?.minimize();
  })

  //登录后的窗口属性
  ipcMain.handle('home-window', () => {
    mainWindow?.setResizable(true);
    //居中
    mainWindow?.center();
  })

  // 主进程保存窗口原始状态
  let originalBounds: any = null;
  //锁定窗口&解锁窗口
  ipcMain.handle('lock-window', (_, isLocked, awayOnTop) => {

    const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().workAreaSize
    if (isLocked) {
      // 1. 保存当前窗口状态
      originalBounds = mainWindow?.getBounds()
      // 计算锁定窗口尺寸：宽度=屏幕1/5，高度=屏幕高度
      const lockWidth = Math.max(Math.floor(screenWidth / 5), 160)
      const lockHeight = screenHeight

      // 计算靠右定位：X坐标 = 屏幕宽度 - 窗口宽度
      const rightPosition = screenWidth - lockWidth
      //锁定后先允许改变大小（否则无法正常显示工具栏）
      mainWindow?.setResizable(true)
      // mainWindow.setBackgroundColor('#FFFFFF')
      // 当isLocked为true时，是否锁定由awayOnTop决定
      mainWindow?.setAlwaysOnTop(awayOnTop)
      mainWindow?.setSize(lockWidth, lockHeight)
      // 靠右定位
      mainWindow?.setPosition(rightPosition, 0)
      // 锁定尺寸
      mainWindow?.setMinimumSize(lockWidth, lockHeight)
      mainWindow?.setMaximumSize(lockWidth, lockHeight)
    } else {
      if (originalBounds) {
        mainWindow?.setBounds(originalBounds)
        mainWindow?.setResizable(true)
        mainWindow?.setAlwaysOnTop(false)
        mainWindow?.setMinimumSize(0, 0)
        mainWindow?.setMaximumSize(0, 0)
      }
    }
  })

  // 存储路径设置
  ipcMain.handle('init-savePath', async () => {
    const appPath = path.dirname(app.getPath('exe')); // 获取安装目录
    const ibearDir = path.join(appPath, 'iBear');

    // 确保目录存在
    if (!existsSync(ibearDir)) {
      mkdirSync(ibearDir, { recursive: true });
    }
    return ibearDir; // 返回完整路径
  });

  // 窗口不可修改大小
  ipcMain.handle('set-window-resizable', (_, isResizable) => {
    mainWindow?.setResizable(isResizable);
  })

  // 最大化窗口和还原
  ipcMain.handle('toggle-maximize-window', (_, isMaximized) => {
    if (isMaximized) {
      mainWindow?.maximize();
    } else {
      mainWindow?.unmaximize();
    }
  })

  // 选择文件夹弹窗
  ipcMain.handle('choose-filepath-dialog', async (_, options) => {
    return await dialog.showOpenDialog(options);
  });

  async function atomicFileLock(filePath, operation) {
    const lockDir = `${filePath}.lock`;
    try {
      await fs.mkdir(lockDir, { recursive: true }); // 创建锁目录
      return await operation(); // 执行文件操作
    } finally {
      await fs.rmdir(lockDir).catch(() => { }); // 解锁（忽略错误）
    }
  }

  //  ts类型定义
  interface ChatEntry {
    role: String;
    content: String;
    time: String
  };

  // 保存聊天记录
  ipcMain.handle('save-chat', async (_, messageObj, storageDir) => {
    try {
      // 1. 文件名称
      const date = new Date(messageObj.time);
      const fileName = `${date.getFullYear()}${(date.getMonth() + 1).toString().padStart(2, '0')}${date.getDate().toString().padStart(2, '0')}.json`;
      const filePath = path.join(storageDir, fileName);
      // 2. 确保目录存在
      await fs.mkdir(storageDir, { recursive: true });

      // 3. 创建消息对象
      const newEntry = {
        role: messageObj.role,
        content: messageObj.content,
        time: messageObj.time
      };
      // 4. 原子锁+文件读写
      return await atomicFileLock(filePath, async () => {
        let existingData: ChatEntry[] = [];
        try {
          const currentData = await fs.readFile(filePath, 'utf-8');
          existingData = JSON.parse(currentData);
        } catch (readErr: any) {
          if (readErr.code !== 'ENOENT') throw readErr;
        }
        existingData.push(newEntry);
        await fs.writeFile(filePath, JSON.stringify(existingData, null, 2));
        return { success: true, filePath };
      });
    } catch (error: any) {
      console.error('保存聊天记录失败:', error.message);
      return { success: false, error: error.message };
    }
  });

  // 加载聊天记录，首次加载当天，当天没有20条时则加载历史记录，每次滚动加载20条
  interface LoadChatParam {
    storagePath: string
    cursor?: { date: string; skip: number }
    pageSize?: number
    isInitial?: boolean
  }

  type Cursor = { date: string; skip: number } | null

  // 主处理函数
  ipcMain.handle('load-chat', async (_, loadChatParam: LoadChatParam) => {
    if (!loadChatParam || typeof loadChatParam !== 'object') {
      throw new Error('入参无效: 预期为对象')
    }
    const { storagePath, cursor = null, pageSize = 20, isInitial = false } = loadChatParam
    if (typeof storagePath !== 'string') {
      throw new Error('存储路径必须是一个有效的路径字符串')
    }
    try {
      // 获取并过滤文件
      const files = (await readdir(storagePath))
        .filter(file => file.endsWith('.json') && /^\d{8}\.json$/.test(file))

      // 按日期排序（最新在前）
      files.sort((a, b) => {
        const dateA = parseInt(a.split('.')[0])
        const dateB = parseInt(b.split('.')[0])
        return dateB - dateA
      })

      // 获取当前日期
      const currentDate = new Date()
      const today = `${currentDate.getFullYear()}${(currentDate.getMonth() + 1).toString().padStart(2, '0')}${currentDate.getDate().toString().padStart(2, '0')}`

      let fileData: any[] = []

      if (isInitial) {
        // 首次加载逻辑
        let remaining = pageSize
        let lastProcessedFile: string | null = null
        let lastProcessedSkip = 0

        // 处理当天文件
        const todayFile = files.find(f => f.split('.')[0] === today)
        if (todayFile) {
          const content = await readAndParseFile(storagePath, todayFile)
          fileData = [...content, ...fileData]
          remaining -= content.length
          lastProcessedFile = todayFile.split('.')[0]
        }

        // 处理历史文件
        for (const file of files) {
          if (remaining <= 0) break
          const fileDate = file.split('.')[0]
          if (fileDate === today) continue

          const content = await readAndParseFile(storagePath, file)
          const take = Math.min(remaining, content.length)
          fileData = [...content.slice(-take), ...fileData]

          lastProcessedFile = fileDate
          lastProcessedSkip = content.length - take
          remaining -= take
        }

        // 设置游标
        const nextCursorVal = lastProcessedFile
          ? { date: lastProcessedFile, skip: lastProcessedSkip }
          : null

        const serializableData = fileData.map(msg => ({
          ...msg,
          // 确保特殊类型被转换为基本类型
          time: msg.time instanceof Date ? msg.time.toISOString() : msg.time
        }))

        return {
          data: serializableData,
          nextCursor: nextCursorVal,
          hasMore: remaining < pageSize
        }
      } else {
        // 滚动加载逻辑
        if (!cursor) return { data: [], nextCursor: null, hasMore: false };

        let collected = 0;
        let currentFileIndex = files.findIndex(f => f.split('.')[0] === cursor.date);
        if (currentFileIndex === -1) return { data: [], nextCursor: null, hasMore: false };
        const chatData: any[] = [];
        let newCursor: Cursor = null;

        // 从游标文件开始向后遍历（历史文件日期更早）
        for (let i = currentFileIndex; i < files.length && collected < pageSize; i++) {
          const file = files[i];
          const fileDate = file.split('.')[0];
          const content = await readAndParseFile(storagePath, file);
          // 确定当前文件的读取起始位置
          const startIndex = (fileDate === cursor.date) ? cursor.skip : 0;
          const remainingInPage = pageSize - collected;
          const endIndex = Math.min(startIndex + remainingInPage, content.length);

          // 读取当前文件片段
          const messages = content.slice(startIndex, endIndex);
          chatData.push(...messages);
          collected += messages.length;
          // 更新游标规则：
          if (endIndex < content.length) {
            // 当前文件未读完：游标停留在当前文件
            newCursor = { date: fileDate, skip: endIndex };
          } else if (i + 1 < files.length) {
            // 当前文件已读完：游标指向下一个文件的起始位置
            newCursor = { date: files[i + 1].split('.')[0], skip: 0 };
          } // 否则 newCursor 保持 null（无更多数据）
        }

        const serializableChatData = chatData.map(msg => ({
          ...msg,
          time: msg.time instanceof Date ? msg.time.toISOString() : msg.time
        })).reverse()

        return {
          data: serializableChatData,
          nextCursor: newCursor,
          hasMore: newCursor !== null // 有游标代表还有数据
        };
      }
    } catch (error) {
      console.error('加载失败:', error)
      return { data: [], nextCursor: null, hasMore: false }
    }
  })

  // 序列化游标对象
  // 辅助函数：读取并解析文件
  async function readAndParseFile(storagePath: string, file: string): Promise<any[]> {
    try {
      const filePath = path.join(storagePath, file)
      const data = await readFile(filePath, 'utf-8')
      return JSON.parse(data) || []
    } catch (error) {
      console.error(`读取文件失败: ${file}`, error)
      return []
    }
  }

  const gotTheLock = app.requestSingleInstanceLock()
  if (!gotTheLock) {
    app.quit()
  } else {
    app.on('second-instance', () => {
      if (mainWindow) {
        mainWindow.show()
        mainWindow.focus()
      }
    })
  }

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }

}


app.whenReady().then(() => {
  electronApp.setAppUserModelId('com.electron')

  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  // 创建存储聊天的文件夹，先获取安装路径，如果存在对应文件夹则不创建
  const installPath = path.dirname(app.getPath('exe')); // 获取安装目录
  const ibearDir = path.join(installPath, 'iBear');

  if (!existsSync(ibearDir)) {
    mkdirSync(ibearDir, { recursive: true });
  }

  ipcMain.handle('get-storage-path', () => {
    return ibearDir;
  });

  // IPC test
  ipcMain.on('ping', () => console.log('pong'))

  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
  // 监听主进程更新通知
  initUpdater(mainWindow);

})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

